#!/usr/bin/env bash
set -euo pipefail

dn=$(dirname "$0")
# shellcheck source=src/cmdlib.sh
. "${dn}"/cmdlib.sh
# shellcheck source=src/libguestfish.sh
. "${dn}"/libguestfish.sh

# Usage: gf-set-platform <input image> <output image> PLATFORMID
# Example: gf-set-platform fedora-coreos.qcow2 fedora-coreos-aws.qcow2 aws
#
# This will add ignition.platform.id=aws to the bootloader arguments. Intended to
# be used for Ignition. It's much faster to do this than generate a fresh image
# for each provider (and also helps ensure the images are otherwise identical).

src="$1"
dest="$2"
platformid="$3"

if [[ $src == *.gz || $src == *.xz ]]; then
    img="$(basename "$src")"
    fatal "Cannot change ignition.platform.id on $img; not an uncompressed image"
fi

set -x
# Work in a tmpdir on the destination so that we don't inherit some MCS labeling
# from the /tmp dir in the container. This also ensures that the final move is a
# pure `rename()`.
# See also:
# https://github.com/coreos/coreos-assembler/issues/292
# https://github.com/coreos/coreos-assembler/pull/394
tmpd=$(mktemp -tdp "$(dirname "${dest}")" gf-set-platform.XXXXXX)
tmp_dest=${tmpd}/box.img

/usr/lib/coreos-assembler/cp-reflink "${src}" "${tmp_dest}"
chmod u+w "${tmp_dest}"

# Mount everything read-only by default
coreos_gf_run_mount ro "${tmp_dest}"
# We just mount the boot partition writable
coreos_gf remount /boot rw:true

# Look up platform-specific configuration
rewrite_grub_cmds=
extra_grub_cmds=
extra_kargs=
remove_kargs=
if [ "$(coreos_gf exists /boot/nestos/platforms.json)" = "true" ]; then
    coreos_gf download /boot/nestos/platforms.json "${tmpd}"/platforms.json
    rewrite_grub_cmds=1
    extra_grub_cmds=$(jq -r ".${platformid}.grub_commands // [] | join(\"\\\\n\")" < "${tmpd}/platforms.json")
    extra_kargs=$(jq -r ".${platformid}.kernel_arguments // [] | join(\" \")" < "${tmpd}/platforms.json")
    remove_kargs=$(jq -r ".qemu.kernel_arguments // [] | join(\" \")" < "${tmpd}/platforms.json")
fi

# Inject PLATFORM label in BLS config (for subsequent config regeneration)
blscfg_path=$(coreos_gf glob-expand /boot/loader/entries/ostree-*.conf)
coreos_gf download "${blscfg_path}" "${tmpd}"/bls.conf
# Remove any platformid currently there
sed -i -e 's, ignition.platform.id=[a-zA-Z0-9]*,,g' "${tmpd}"/bls.conf
sed -i -e '/^options / s,$, ignition.platform.id='"${platformid}"',' "${tmpd}"/bls.conf
if [ -n "$remove_kargs" ]; then
    # Remove existing qemu-specific kargs
    sed -i -e '/^options / s@ '"${remove_kargs}"'@@' "${tmpd}"/bls.conf
fi
if [ -n "$extra_kargs" ]; then
    sed -i -e '/^options / s@$@ '"${extra_kargs}"'@' "${tmpd}"/bls.conf
fi
coreos_gf upload "${tmpd}"/bls.conf "${blscfg_path}"

if [ -n "$rewrite_grub_cmds" ]; then
    # Remove qemu-specific grub.cfg commands and inject any new ones
    coreos_gf download /boot/grub2/grub.cfg "${tmpd}"/grub-orig.cfg
    awk '/^# CONSOLE-SETTINGS-START$/ {suspend=1; print} {if (!suspend) print} /^# CONSOLE-SETTINGS-END$/ {suspend=0; print}' "${tmpd}"/grub-orig.cfg | \
        sed -E 's@(^# CONSOLE-SETTINGS-START$)@\1'"${extra_grub_cmds:+\\n${extra_grub_cmds}}"'@' \
        > "${tmpd}"/grub.cfg
    coreos_gf upload "${tmpd}"/grub.cfg /boot/grub2/grub.cfg
fi

if [ "$basearch" = "s390x" ] ; then
    # Before we re-run zipl make sure we have the firstboot options
    # There's a similar hack in create_disk.sh
    sed -i -e 's|^\(options .*\)|\1 ignition.firstboot|' "${tmpd}"/bls.conf
    coreos_gf rename "${blscfg_path}" "${blscfg_path}.orig"
    coreos_gf upload "${tmpd}"/bls.conf "${blscfg_path}"

    coreos_gf debug sh "mount -o bind /sysroot/boot /sysroot/${deploydir}/boot"
    # guestfish tries to create a /dev when doing a chroot. Mount it here as the filesystem is read only
    coreos_gf debug sh "mount -t devtmpfs none /sysroot/${deploydir}/dev"
    # zipl wants /proc
    coreos_gf debug sh "mount -t proc none /sysroot/${deploydir}/proc"
    coreos_gf debug sh "chroot /sysroot/${deploydir} /usr/sbin/zipl"
    coreos_gf debug sh "umount /sysroot/${deploydir}/proc /sysroot/${deploydir}/boot"
    # Remove firstboot options after running zipl as we don't want them to persist
    coreos_gf rename "${blscfg_path}.orig" "${blscfg_path}"
fi

# fsck the boot partition, since we were seeing some corruption with a
# reflink-backed file on the host https://github.com/coreos/coreos-assembler/pull/935
# and this will verify whether it happened
coreos_gf umount-all
bootpn=$(coreos_gf findfs-label boot)
coreos_gf e2fsck "${bootpn}" correct:false forceall:true

coreos_gf_shutdown

mv "${tmp_dest}" "${dest}"
rm "${tmpd}" -rf
